import * as React from "react";
import requestUtils from "../../utils/RequestUtils";
import PropTypes from "prop-types";

/**
 * form组件，错误提示和数据提交
 * props: {
 *     action: {string} 提交地址,
 *     method: {string} 提交方法，默认“get”,
 *     onSubmit: {function} 提交事件,
 *     onSuccess: {function} 提交成功回调
 * }
 */
export default class Form extends React.Component{
    static propTypes = {
        action: PropTypes.string,
        method: PropTypes.string,
        onSubmit: PropTypes.func,
        onSuccess: PropTypes.func
    };
    /**
     * 默认属性
     */
    static defaultProps = {
        onSuccess: function() {},
        onSubmit: function () {},
        method: "get"
    };
    constructor(props){
        super(props);
        this.submitHandler = this.submitHandler.bind(this);
    }
    submitHandler(event){
        event.preventDefault();
        if(!this.formElement.reportValidity()) return;
        if(this.props.onSubmit(event) === false) return;
        let action = this.props.action;
        if(!action){
            console.warn("没有设置action属性的Form", this.formElement);
            return ;
        }
        let options = {
            method: this.props.method
        };
        if(this.props.method === "get"){
            options.params = this.getData();
        }else{
            options.data = this.getData();
        }
        requestUtils.ajax(action, options)
            .then(res=>{
                this.props.onSuccess(res);
            })
            .catch(res=>{
                console.log(res);
            })
    }

    /**
     * 对options进行转换,放在循环中会报Don't make functions within a loop  no-loop-func
     */
    static formatterOptions(input, {value, selected, disabled}){
        return {
            name: input.name,
            value: value,
            selected: selected,
            disabled: disabled
        };
    }

    /**
     * 获取Form数据
     */
    getData(){
        let data = {};
        let inputs = Array.from(this.formElement);
        let input;
        while ((input = inputs.pop()) != null) {
            if(!input.name || input.disabled) continue;
            let value = data[input.name];
            switch (input.type) {
                case "select-multiple":
                    inputs.push(...Array.from(input.options).map(Form.formatterOptions.bind(input)));
                    break;
                case "checkbox":
                    let checkBoxValue = input.getAttribute("value");
                    if(value instanceof Array){
                        if(input.checked){
                            value.push(checkBoxValue || true);
                        }else if(checkBoxValue === null){
                            value.push(false)
                        }
                    }else if(value){
                        if(input.checked){
                            data[input.name] = [value, checkBoxValue || true];
                        }else if(checkBoxValue === null){
                            data[input.name] = [value, false];
                        }
                    }else{
                        if(input.checked){
                            data[input.name] = checkBoxValue || true;
                        }else if(checkBoxValue === null){
                            data[input.name] = false;
                        }
                    }
                    break;
                case "radio":
                    data[input.name] = input.value;
                    break;
                default:
                    if(input.value === "" && !input.hasAttribute("must")) break;
                    if(value instanceof Array){
                        value.push(input.value);
                    }else{
                        data[input.name] = input.value;
                    }
                    break;
            }
        }
        return data;
    }
    render() {
        return <form
            ref={element=>this.formElement=element}
            onSubmit={this.submitHandler}
            className={this.props.className}
        >
            {this.props.children}
        </form>
    }
}
